import tkinter as tk
from tkinter import filedialog, messagebox, scrolledtext
import os
import shutil
import zipfile
import tempfile
import re
from pathlib import Path

class FileSelectorApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Mind+ 用户库升级助手")

        # 创建第一个文件选择框及其标签
        self.label1 = tk.Label(root, text="选择用户库:")
        self.label1.grid(row=0, column=0, padx=10, pady=5)
        self.entry1 = tk.Entry(root, width=50)
        self.entry1.grid(row=0, column=1, padx=10, pady=5)
        self.button1 = tk.Button(root, text="浏览", command=lambda: self.browse_file(1))
        self.button1.grid(row=0, column=2, padx=10, pady=5)

        # 创建第二个文件/文件夹选择框及其标签
        self.label2 = tk.Label(root, text="选择工程(文件/文件夹):")
        self.label2.grid(row=1, column=0, padx=10, pady=5)
        self.entry2 = tk.Entry(root, width=50)
        self.entry2.grid(row=1, column=1, padx=10, pady=5)
        self.button2 = tk.Button(root, text="浏览文件", command=lambda: self.browse_file(2))
        self.button2.grid(row=1, column=2, padx=5, pady=5)
        self.button2_folder = tk.Button(root, text="浏览文件夹", command=lambda: self.browse_folder(2))
        self.button2_folder.grid(row=1, column=3, padx=5, pady=5)

        # 创建执行按钮
        self.execute_button = tk.Button(root, text="执行", command=self.execute)
        self.execute_button.grid(row=2, column=0, columnspan=4, pady=20)

        # 创建日志窗口
        self.log_text = scrolledtext.ScrolledText(root, width=70, height=15)
        self.log_text.grid(row=3, column=0, columnspan=4, padx=10, pady=10)

    def browse_file(self, file_number):
        if file_number == 1:
            filetypes = [("MPExt Files", "*.mpext")]
            filename = filedialog.askopenfilename(filetypes=filetypes)
        elif file_number == 2:
            filetypes = [("MP Files", "*.mp")]
            filename = filedialog.askopenfilename(filetypes=filetypes)

        if filename:
            if file_number == 1:
                self.entry1.delete(0, tk.END)
                self.entry1.insert(0, filename)
            elif file_number == 2:
                self.entry2.delete(0, tk.END)
                self.entry2.insert(0, filename)

    def browse_folder(self, file_number):
        if file_number == 2:
            foldername = filedialog.askdirectory()
            if foldername:
                self.entry2.delete(0, tk.END)
                self.entry2.insert(0, foldername)

    def log(self, message):
        """添加日志并自动滚动到底部"""
        self.log_text.insert(tk.END, message + "\n")
        self.log_text.see(tk.END)
        self.root.update()

    def process_single_mp_file(self, mpext_file, mp_file, name, vision):
        """处理单个mp文件的升级"""
        mp_file_path = Path(mp_file)
        mp_dir = mp_file_path.parent
        mp_filename = mp_file_path.name
        
        # 创建tmp备份目录
        tmp_dir = mp_dir / "tmp"
        tmp_dir.mkdir(exist_ok=True)
        self.log(f"创建备份目录: {tmp_dir}")
        
        # 备份原文件到tmp目录
        backup_file = tmp_dir / mp_filename
        shutil.copy2(mp_file, backup_file)
        self.log(f"已备份原文件到: {backup_file}")
        
        # 创建临时替换目录
        with tempfile.TemporaryDirectory() as temp_dir:
            # 解压用户库到 name 文件夹
            file1_extract_dir = os.path.join(temp_dir, name)
            os.makedirs(file1_extract_dir)
            with zipfile.ZipFile(mpext_file, 'r') as zip_ref:
                zip_ref.extractall(file1_extract_dir)
            self.log(f"用户库已解压到: {file1_extract_dir}")
            
            # 解压工程
            file2_extract_dir = os.path.join(temp_dir, 'file2')
            os.makedirs(file2_extract_dir)
            with zipfile.ZipFile(mp_file, 'r') as zip_ref:
                zip_ref.extractall(file2_extract_dir)
            self.log(f"工程已解压到: {file2_extract_dir}")
            
            # 检查 file2_extract_dir 中是否存在 name 文件夹
            target_dir = os.path.join(file2_extract_dir, name)
            if not os.path.exists(target_dir):
                self.log(f"警告: 该工程 {name} 用户库不存在，跳过此文件")
                return False
            
            # 如果存在，先删除 file2_extract_dir 下面的 name 文件夹
            shutil.rmtree(target_dir)
            self.log(f"已删除旧用户库: {target_dir}")
            
            # 将文件1解压后的 file1_extract_dir 文件夹拷贝到 file2_extract_dir
            shutil.copytree(file1_extract_dir, target_dir, dirs_exist_ok=True)
            self.log(f"用户库的内容已拷贝到工程的目录中")
            
            # 重新打包工程，不带版本后缀，直接替换原文件
            new_file2_full_path = mp_file  # 直接使用原文件路径
            with zipfile.ZipFile(new_file2_full_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
                for foldername, subfolders, filenames in os.walk(file2_extract_dir):
                    for filename in filenames:
                        file_path = os.path.join(foldername, filename)
                        arcname = os.path.relpath(file_path, file2_extract_dir)
                        zipf.write(file_path, arcname)
            self.log(f"工程已重新打包并替换: {new_file2_full_path}")
            return True

    def execute(self):
        file1 = self.entry1.get()
        file2 = self.entry2.get()

        if not file1 or not file2:
            messagebox.showwarning("警告", "请选择用户库和工程")
            return

        if not file1.endswith('.mpext'):
            messagebox.showwarning("警告", "用户库必须是 .mpext 文件")
            return

        # 提取 name 和 vision 信息
        match = re.match(r'(.+)-(V\d+\.\d+\.\d+)\.mpext$', os.path.basename(file1))
        if not match:
            messagebox.showwarning("警告", "用户库的命名格式不正确，应为 'name-vision.mpext'")
            return

        name, vision = match.groups()
        self.log_text.delete(1.0, tk.END)  # 清空日志
        self.log(f"提取的 name: {name}, vision: {vision}")
        self.log("=" * 60)

        # 判断file2是文件还是文件夹
        file2_path = Path(file2)
        mp_files = []
        
        if file2_path.is_file():
            if not file2.endswith('.mp'):
                messagebox.showwarning("警告", "工程必须是 .mp 文件")
                return
            mp_files = [file2]
        elif file2_path.is_dir():
            # 遍历文件夹中的所有.mp文件
            mp_files = list(file2_path.glob("*.mp"))
            if not mp_files:
                messagebox.showwarning("警告", "文件夹中没有找到 .mp 文件")
                return
            self.log(f"在文件夹中找到 {len(mp_files)} 个 .mp 文件")
        else:
            messagebox.showwarning("警告", "工程路径无效")
            return

        # 处理每个mp文件
        success_count = 0
        fail_count = 0
        
        for i, mp_file in enumerate(mp_files, 1):
            self.log(f"\n处理文件 {i}/{len(mp_files)}: {mp_file.name}")
            self.log("-" * 60)
            try:
                if self.process_single_mp_file(file1, str(mp_file), name, vision):
                    success_count += 1
                    self.log(f"✓ 成功处理: {mp_file.name}")
                else:
                    fail_count += 1
                    self.log(f"✗ 跳过: {mp_file.name}")
            except Exception as e:
                fail_count += 1
                error_msg = f"✗ 处理失败: {mp_file.name} - {str(e)}"
                self.log(error_msg)
                print(f"错误详情: {e}")

        # 显示总结
        self.log("\n" + "=" * 60)
        self.log(f"处理完成！成功: {success_count}, 失败/跳过: {fail_count}")
        messagebox.showinfo("完成", f"操作已完成！\n成功: {success_count}\n失败/跳过: {fail_count}")

if __name__ == "__main__":
    root = tk.Tk()
    app = FileSelectorApp(root)
    root.mainloop()